//==================================================================
/// road.h
///
/// Created by Davide Pasca - 2009/10/5
/// See the file "license.txt" that comes with this project for
/// copyright info. 
//==================================================================

#ifndef ROAD_H
#define ROAD_H

#include "sector_list.h"

#define GR_TO_RAD	(3.14159265f/180.0f)

//==================================================================
class vehicle;

//==================================================================
class road
{
	float		mFarSectorY;
	int			mMinYPosSS; // minimum Y value touched while rendering (in screen-space)
	int			_x, _y, _pos;
	U32			mScreenWd;
	U32			mScreenHe;
	int			_road_w;
	int			_lane_w;
	int			_strip_h;
	transformer *mpXFormer;
	color		_road_col_lt;
	color		_road_col_dk;
	color		_line_col;
	color		_line_mip_col;
	color		_edge_a_col, _edge_b_col;

	color		_side_lt_col, _side_dk_col;
	color		_fog_col;

	// patch in world-space
	class PatchWS
	{
	public:
		int	xs[4];
		int	y;
	};

	// patch in screen-space
	class PatchSS
	{
	public:
		int	xs[4];
		int	y;
		float z;
	};

public:
	DVec<PatchSS>	mSPatches;
	DVec<PatchWS>	mWPatches;

	float				_cur_xacc;

	static const int	ANGLE=0;
	static const int	LANES=1;
	static const int	VANGLE=2;
	static const int	VIEW_PATCHES=120;
	//static const float	GR_TO_RAD=3.14159265f/180.0f;
	static const int	MAX_SIDE_SPRT=3;

	adel<SectorList>	mpoRdSec;

	SectorList			*mpSprtsLSec[ MAX_SIDE_SPRT ];
	SectorList			*mpSprtsRSec[ MAX_SIDE_SPRT ];

	static const int LSIDE=0, RSIDE=1;
	static const int L1=2, R1=3;
	static const int L2=4, R2=5;
	static const int L3=6, R3=7;

	DVec<vehicle*>	*mppVehicles;
	DVec<vehicle*>	mpVList;
	const vehicle	*mpCollidedVehicle;
	float			mCollidedVehicleStrength;

public:
	//==================================================================
	road( transformer *pXFormer );
	~road();

	void Resize( U32 w, U32 h, U32 lane_w, U32 strip_h );

	//==================================================================
	void sector_add( int lanes, int vangle, int angle, int len );

	//==================================================================
	SectorList *get_sector( int sec_type );

	//==================================================================
	void sector_sprites_add( int sec_type, sprite *pSprt, int len, int step, int off )
	{
		SectorDef	def;
		def.len		= len;
		def.step	= step;
		def.offX	= off;
		def.mpObj	= pSprt;
		get_sector( sec_type )->add( def );
	}

	//==================================================================
	void sector_sprites_add( int sec_type, int len )
	{
		sector_sprites_add_empty( sec_type, len );
	}
		
	//==================================================================
	void sector_sprites_add_empty( int sec_type, int len )
	{
		SectorDef	def;
		def.len = len;

		get_sector( sec_type )->add( def );
	}

	//==================================================================
	color col_mod( const color &col, float coe )
	{
		return color(
				(int)(col.rgba[0] * coe),
				(int)(col.rgba[1] * coe),
				(int)(col.rgba[2] * coe) );
	}

	//==================================================================
	color col_mod( int r, int g, int b, float coe )
	{
		return color(
				(int)(r * coe),
				(int)(g * coe),
				(int)(b * coe) );
	}

	//==================================================================
	void colors_set(
			  const color &road,
			  const color &line,
			  const color &edge_a,
			  const color &edge_b,
			  const color &side,
			  const color &fog
			);

	//==================================================================
	void draw_patch(
			graphics &g,
			float x1a,
			float x2a,
			float ya,
			float x1b,
			float x2b,
			float yb,
			int road_col,
			float edge_w_coe,
			int edge_col,
			float line_w_coe,
			int draw_line );

	//==================================================================
	void prepare_vehicle_list( DVec<vehicle*> &v_list, int pos_base );

	//==================================================================
	void draw_vehicles(
				graphics &g,
				DVec<vehicle*> &v_list,
				int pos,
				int base_pos,
				float r_x,
				float r_y,
				bool check_collision );

	//==================================================================
	bool sector_draw( graphics &g, DVec<vehicle*> &v_list, int pos );

	//==================================================================
	bool paint( graphics &g )
	{
		prepare_vehicle_list( mpVList, _pos );
		return sector_draw( g, mpVList, _pos );
	}

	//==================================================================
	void pos_set( int pos )
	{
		_pos = pos;
	}

	//==================================================================
	int pos_get() const
	{
		return _pos;
	}

	//==================================================================
	int far_pos_get() const
	{
		return _pos + _strip_h * VIEW_PATCHES;
	}

	//==================================================================
	int edge_collision( int x, int y, int z );

	//==================================================================
	int x_off( int x )
	{
		return _x += x;
	}

	//==================================================================
	float y_get() const { return mFarSectorY; }

	//==================================================================
	const vehicle *collided_vehicle() const;

	//==================================================================
	float collided_vehicle_strength();

	//==================================================================
	void vehicles_set( DVec<vehicle*> &pList );

private:
	void drawSideObjs(
				graphics	&g,
				SectorList	**slist_array,
				SectorListIter	*pIter,
				int obj_posi,
				float org_x,
				float obj_sy,
				float obj_zz,
				u_int flags
			) const;
};

#endif
